package org.nehc.algorithm.redissonutils;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.time.Duration;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * Redisson 本地缓存管理工具类
 * 提供本地缓存管理功能，用于提升性能
 *
 * @author system
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RedissonLocalCacheUtils {

    /**
     * 本地缓存实例映射
     */
    private static final Map<String, Cache<String, Object>> LOCAL_CACHE_MAP = new ConcurrentHashMap<>();

    /**
     * 默认缓存名称
     */
    private static final String DEFAULT_CACHE_NAME = "default";

    /**
     * 默认缓存配置
     */
    private static final Cache<String, Object> DEFAULT_CACHE = Caffeine.newBuilder()
            .maximumSize(10000)
            .expireAfterWrite(Duration.ofMinutes(30))
            .expireAfterAccess(Duration.ofMinutes(10))
            .build();

    static {
        LOCAL_CACHE_MAP.put(DEFAULT_CACHE_NAME, DEFAULT_CACHE);
    }

    // ==================== 缓存实例管理 ====================

    /**
     * 创建或获取缓存实例
     *
     * @param cacheName 缓存名称
     * @param maxSize   最大缓存大小
     * @param expireAfterWrite 写入后过期时间
     * @param expireAfterAccess 访问后过期时间
     * @return 缓存实例
     */
    public static Cache<String, Object> getOrCreateCache(String cacheName, long maxSize,
                                                         Duration expireAfterWrite, Duration expireAfterAccess) {
        return LOCAL_CACHE_MAP.computeIfAbsent(cacheName, k ->
            Caffeine.newBuilder()
                    .maximumSize(maxSize)
                    .expireAfterWrite(expireAfterWrite)
                    .expireAfterAccess(expireAfterAccess)
                    .build()
        );
    }

    /**
     * 获取默认缓存实例
     *
     * @return 默认缓存实例
     */
    public static Cache<String, Object> getDefaultCache() {
        return DEFAULT_CACHE;
    }

    /**
     * 获取指定名称的缓存实例
     *
     * @param cacheName 缓存名称
     * @return 缓存实例，如果不存在则返回null
     */
    public static Cache<String, Object> getCache(String cacheName) {
        return LOCAL_CACHE_MAP.get(cacheName);
    }

    /**
     * 移除缓存实例
     *
     * @param cacheName 缓存名称
     * @return 被移除的缓存实例，如果不存在则返回null
     */
    public static Cache<String, Object> removeCache(String cacheName) {
        if (DEFAULT_CACHE_NAME.equals(cacheName)) {
            log.warn("Cannot remove default cache");
            return null;
        }
        return LOCAL_CACHE_MAP.remove(cacheName);
    }

    /**
     * 获取所有缓存名称
     *
     * @return 缓存名称集合
     */
    public static Set<String> getCacheNames() {
        return LOCAL_CACHE_MAP.keySet();
    }

    // ==================== 缓存操作（默认缓存） ====================

    /**
     * 设置缓存值
     *
     * @param key   缓存key
     * @param value 缓存值
     */
    public static void set(String key, Object value) {
        DEFAULT_CACHE.put(key, value);
    }

    /**
     * 获取缓存值
     *
     * @param key 缓存key
     * @return 缓存值
     */
    public static Object get(String key) {
        return DEFAULT_CACHE.getIfPresent(key);
    }

    /**
     * 获取缓存值（带类型转换）
     *
     * @param key   缓存key
     * @param clazz 目标类型
     * @return 缓存值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(String key, Class<T> clazz) {
        Object value = DEFAULT_CACHE.getIfPresent(key);
        if (value != null && clazz.isInstance(value)) {
            return (T) value;
        }
        return null;
    }

    /**
     * 获取缓存值，如果不存在则使用加载函数加载
     *
     * @param key    缓存key
     * @param loader 加载函数
     * @return 缓存值
     */
    public static Object get(String key, Function<String, Object> loader) {
        return DEFAULT_CACHE.get(key, loader);
    }

    /**
     * 删除缓存值
     *
     * @param key 缓存key
     */
    public static void delete(String key) {
        DEFAULT_CACHE.invalidate(key);
    }

    /**
     * 批量删除缓存值
     *
     * @param keys 缓存key集合
     */
    public static void delete(Iterable<String> keys) {
        DEFAULT_CACHE.invalidateAll(keys);
    }

    /**
     * 清空所有缓存
     */
    public static void clear() {
        DEFAULT_CACHE.invalidateAll();
    }

    /**
     * 检查缓存是否存在
     *
     * @param key 缓存key
     * @return true=存在；false=不存在
     */
    public static boolean exists(String key) {
        return DEFAULT_CACHE.getIfPresent(key) != null;
    }

    /**
     * 获取缓存大小
     *
     * @return 缓存大小
     */
    public static long size() {
        return DEFAULT_CACHE.estimatedSize();
    }

    /**
     * 获取缓存统计信息
     *
     * @return 缓存统计信息
     */
    public static com.github.benmanes.caffeine.cache.stats.CacheStats stats() {
        return DEFAULT_CACHE.stats();
    }

    // ==================== 缓存操作（指定缓存） ====================

    /**
     * 设置缓存值（指定缓存）
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @param value     缓存值
     */
    public static void set(String cacheName, String key, Object value) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            cache.put(key, value);
        } else {
            log.warn("Cache '{}' not found", cacheName);
        }
    }

    /**
     * 获取缓存值（指定缓存）
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @return 缓存值
     */
    public static Object get(String cacheName, String key) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            return cache.getIfPresent(key);
        }
        log.warn("Cache '{}' not found", cacheName);
        return null;
    }

    /**
     * 获取缓存值（指定缓存，带类型转换）
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @param clazz     目标类型
     * @return 缓存值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(String cacheName, String key, Class<T> clazz) {
        Object value = get(cacheName, key);
        if (clazz.isInstance(value)) {
            return (T) value;
        }
        return null;
    }

    /**
     * 获取缓存值，如果不存在则使用加载函数加载（指定缓存）
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @param loader    加载函数
     * @return 缓存值
     */
    public static Object get(String cacheName, String key, Function<String, Object> loader) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            return cache.get(key, loader);
        }
        log.warn("Cache '{}' not found", cacheName);
        return loader.apply(key);
    }

    /**
     * 删除缓存值（指定缓存）
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     */
    public static void delete(String cacheName, String key) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            cache.invalidate(key);
        } else {
            log.warn("Cache '{}' not found", cacheName);
        }
    }

    /**
     * 批量删除缓存值（指定缓存）
     *
     * @param cacheName 缓存名称
     * @param keys      缓存key集合
     */
    public static void delete(String cacheName, Iterable<String> keys) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            cache.invalidateAll(keys);
        } else {
            log.warn("Cache '{}' not found", cacheName);
        }
    }

    /**
     * 清空指定缓存
     *
     * @param cacheName 缓存名称
     */
    public static void clear(String cacheName) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            cache.invalidateAll();
        } else {
            log.warn("Cache '{}' not found", cacheName);
        }
    }

    /**
     * 检查缓存是否存在（指定缓存）
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @return true=存在；false=不存在
     */
    public static boolean exists(String cacheName, String key) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            return cache.getIfPresent(key) != null;
        }
        log.warn("Cache '{}' not found", cacheName);
        return false;
    }

    /**
     * 获取缓存大小（指定缓存）
     *
     * @param cacheName 缓存名称
     * @return 缓存大小
     */
    public static long size(String cacheName) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            return cache.estimatedSize();
        }
        log.warn("Cache '{}' not found", cacheName);
        return 0;
    }

    /**
     * 获取缓存统计信息（指定缓存）
     *
     * @param cacheName 缓存名称
     * @return 缓存统计信息
     */
    public static CacheStats stats(String cacheName) {
        Cache<String, Object> cache = getCache(cacheName);
        if (cache != null) {
            return cache.stats();
        }
        log.warn("Cache '{}' not found", cacheName);
        return null;
    }

    // ==================== 便捷方法 ====================

    /**
     * 清空所有缓存实例
     */
    public static void clearAll() {
        LOCAL_CACHE_MAP.values().forEach(Cache::invalidateAll);
    }

    /**
     * 获取所有缓存的总大小
     *
     * @return 总缓存大小
     */
    public static long totalSize() {
        return LOCAL_CACHE_MAP.values().stream()
                .mapToLong(Cache::estimatedSize)
                .sum();
    }

    /**
     * 执行所有缓存的清理操作
     */
    public static void cleanUp() {
        LOCAL_CACHE_MAP.values().forEach(Cache::cleanUp);
    }

    /**
     * 获取缓存实例数量
     *
     * @return 缓存实例数量
     */
    public static int getCacheCount() {
        return LOCAL_CACHE_MAP.size();
    }

    /**
     * 检查缓存实例是否存在
     *
     * @param cacheName 缓存名称
     * @return true=存在；false=不存在
     */
    public static boolean cacheExists(String cacheName) {
        return LOCAL_CACHE_MAP.containsKey(cacheName);
    }

    /**
     * 删除缓存实例
     *
     * @param cacheName 缓存名称
     */
    public static void invalidateLocalCache(final String cacheName, final String key){
        LOCAL_CACHE_MAP.get(cacheName).invalidate(key);
    }
}
